/**
 * 
 */
package com.wolfpire.proms.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.jbpm.pvm.internal.task.TaskImpl;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.wolfpire.proms.model.Task;
import com.wolfpire.proms.service.TaskService;
import com.wolfpire.system.common.AuthorityUtils;
import com.wolfpire.system.common.Constants;
import com.wolfpire.system.common.EasyuiPage;
import com.wolfpire.system.common.EasyuiPagination;
import com.wolfpire.system.common.Page;
import com.wolfpire.system.common.Result;
import com.wolfpire.system.common.springmvc.PrincipalArgument;
import com.wolfpire.system.model.Authority;
import com.wolfpire.system.model.DataDict;
import com.wolfpire.system.model.User;
import com.wolfpire.system.service.DataDictService;
import com.wolfpire.workflow.em.OperateType;
import com.wolfpire.workflow.om.Forms;
import com.wolfpire.workflow.om.MyTask;
import com.wolfpire.workflow.om.Node;
import com.wolfpire.workflow.om.Operate;
import com.wolfpire.workflow.om.ProInstance;
import com.wolfpire.workflow.om.Workflow;
import com.wolfpire.workflow.spring.FormsService;
import com.wolfpire.workflow.spring.JbpmService;
import com.wolfpire.workflow.spring.MyTaskService;
import com.wolfpire.workflow.spring.NodeService;
import com.wolfpire.workflow.spring.OperateService;
import com.wolfpire.workflow.spring.ProInstanceService;
import com.wolfpire.workflow.spring.WorkflowService;
import com.wolfpire.workflow.spring.impl.JbpmTaskService;

/**
 * @author lihd
 *
 */

@Controller
@RequestMapping("/taskWorkflow")
public class TaskWorkflowController {
	
	@Resource private TaskService taskService;
	
	@Resource private NodeService nodeService;
	
	@Resource private WorkflowService workflowService;
	
	@Resource private JbpmTaskService jbpmTaskService;
	
	@Resource private JbpmService jbpmService;
	
	@Resource private ProInstanceService proInstanceService;
	
	@Resource private FormsService formsService;
	
	@Resource private OperateService operateService;
	
	@Resource private MyTaskService myTaskService;
	
	@Resource private DataDictService dataDictService;
	
	@RequestMapping("/apply")
	public ModelAndView apply(@PrincipalArgument User user,
			@RequestParam Long menuId,
			@RequestParam(value = "page", required = false) String page) {
		//获取对应菜单的操作权限
//		List<Authority> operAuthorities = getAperAuthorities(user, menuId);
		List<Authority> operAuthorities = AuthorityUtils.getAperAuthorities(user, menuId);
		String viewName = "proms/taskWorkflow/taskWorkflow_apply_list";
		if (StringUtils.isNotBlank(page)) {
			viewName = viewName + "_" + page;
		}
		return new ModelAndView(viewName, "operAuthorities", operAuthorities);
	}

	@ResponseBody
	@RequestMapping("/applyList")
	public EasyuiPagination<Map<String, Object>> applyList(
			EasyuiPage<Map<String, Object>>page,
			Task filterTask,
			@PrincipalArgument User user) {
		// TODO: 是否考虑用VO
		filterTask.setCreateUserId(user.getId());
		Page<Map<String, Object>> tasks = this.taskService.setPageApplyDataList(page, filterTask);
		return new EasyuiPagination<Map<String, Object>>(tasks);
	}
	
	@RequestMapping(value = "/add")
	public ModelAndView add(HttpSession session, Task task) {
		ModelAndView mv = new ModelAndView("proms/taskWorkflow/taskWorkflow_add");
		
		// TODO:这里不能单单考虑只有一种流程的情况，更希望的是有多种选择
		Workflow workflow = this.workflowService.get(Constants.TASK_WORKFLOW_ID);
		Node node = this.nodeService.getNode(workflow.getDeploymentId(), Constants.TASK_NODE_2);
		List<Node> taskNodes = new ArrayList<Node>();
		taskNodes.add(node);
		mv.getModelMap().put("taskNodes", taskNodes);
		mv.getModelMap().put("deploymentId", workflow.getDeploymentId());
		mv.getModelMap().put("task", task);
		DataDict isTaskPlan = this.dataDictService.findUniqueByCode(Constants.DATA_DICT_CODE_TASKPLAN);
		if (null != isTaskPlan) {
			mv.getModelMap().put("isTaskPlan", isTaskPlan.getRemark());
		} else {
			mv.getModelMap().put("isTaskPlan", StringUtils.EMPTY);
		}
//		mv.getModelMap().addAttribute(task);
		return mv;
	}
	
	@ResponseBody
	@RequestMapping("/save")
	public Result save(@PrincipalArgument User user,
			@RequestParam(value = "userIds") String userIds,
			@RequestParam(value = "userNames") String userNames,
			Task task) {
		try {
			task.setCreateUserId(user.getId());
			task.setCreateUserName(user.getNickName());
			task.setCreateTime(new Date());
			task.setStatus(Constants.TASK_STATUS_APPLY);
			String[] fundSourcesArray = task.getFundSourcesArray();
			if (ArrayUtils.isNotEmpty(fundSourcesArray)) {
				task.setFundSources(StringUtils.join(fundSourcesArray, ","));
			}
			this.taskService.saveOrUpdate(task);
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("userIds", String.valueOf(user.getId()));
			ProInstance proInstance = this.workflowService.startProcess(Constants.TASK_WORKFLOW_ID, task.getId(), user, params);
			// 再提交至“审批”
			Map<String, Object> data = this.jbpmTaskService.getData(String.valueOf(proInstance.getInstanceId()));
			this.jbpmTaskService.subWorkFlowSingle(data.get("WF_DBID_").toString(), Constants.TASK_NODE_2, userIds, StringUtils.EMPTY, user, OperateType.PASS.getIndex());
			return new Result(true, "保存成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false, "保存失败");
		}
	}
	
	@ResponseBody
	@RequestMapping("/reSave")
	public Result reSave(@PrincipalArgument User user,
			@RequestParam(value = "userIds") String userIds,
			@RequestParam(value = "userNames") String userNames,
			@RequestParam(value = "instanceId") Long instanceId,
			@RequestParam(value = "wfTaskId") String wfTaskId,
			@RequestParam(value = "nextNode") String nextNodeName,
			@RequestParam(value = "advice", required = false) String advice,
			Task task) {
		try {
			task.setCreateUserId(user.getId());
			task.setCreateUserName(user.getNickName());
			task.setCreateTime(new Date());
			task.setStatus(Constants.TASK_STATUS_APPLY);
			String[] fundSourcesArray = task.getFundSourcesArray();
			if (ArrayUtils.isNotEmpty(fundSourcesArray)) {
				task.setFundSources(StringUtils.join(fundSourcesArray, ","));
			}
			this.taskService.saveOrUpdate(task);
//			Map<String, Object> params = new HashMap<String, Object>();
//			params.put("userIds", String.valueOf(user.getId()));
//			ProInstance proInstance = this.workflowService.startProcess(Constants.TASK_WORKFLOW_ID, task.getId(), user, params);
			// 再提交至“审批”
//			Map<String, Object> data = this.jbpmTaskService.getData(String.valueOf(proInstance.getInstanceId()));
//			this.jbpmTaskService.subWorkFlowSingle(wfTaskId, Constants.TASK_NODE_2, userIds, StringUtils.EMPTY, user, OperateType.PASS.getIndex());
			Map<String, Object> result = this.jbpmTaskService
					.subWorkFlowSingle(wfTaskId, nextNodeName, userIds, advice,
							user, OperateType.PASS.getIndex());
			boolean success = (Boolean) result.get("success");
			// 判断流程是否结束
			boolean isEnd = jbpmService.flowIsEnd(result.get("instanceId").toString(), (Node)result.get("nextNode"));
			if (isEnd) {
				task.setStatus(Constants.TASK_STATUS_AGREE);
				this.taskService.save(task);
			}
			return new Result(success, "保存成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false, "保存失败");
		}
	}
	
	@RequestMapping("/todo")
	public ModelAndView todo(@PrincipalArgument User user,
			@RequestParam Long menuId,
			@RequestParam(value = "page", required = false) String page) {
		//获取对应菜单的操作权限
//		List<Authority> operAuthorities = getAperAuthorities(user, menuId);
		List<Authority> operAuthorities = AuthorityUtils.getAperAuthorities(user, menuId);
		String viewName = "proms/taskWorkflow/taskWorkflow_todo_list";
		if (StringUtils.isNotBlank(page)) {
			viewName = viewName + "_" + page;
		}
		return new ModelAndView(viewName, "operAuthorities", operAuthorities);
	}
	
	@ResponseBody
	@RequestMapping("/todoList")
	public EasyuiPagination<Map<String, Object>> todoList(
			EasyuiPage<Map<String, Object>>page,
			Task filterTask,
			@PrincipalArgument User user) {
		// TODO: 是否考虑用VO
		filterTask.setCreateUserId(user.getId());
		Page<Map<String, Object>> tasks = this.taskService.setPageTodoDataList(page, filterTask);
		return new EasyuiPagination<Map<String, Object>>(tasks);
	}
	
	@RequestMapping("/handleTabs")
	public ModelAndView handleTabs(
			@RequestParam(value = "taskId") String taskId,
			@RequestParam(value = "instanceId") Long instanceId,
			@RequestParam(value = "id") Long id,
			ModelMap map) {
		ModelAndView mv = new ModelAndView("proms/taskWorkflow/taskWorkflow_handle_tabs");
		try {
			map.put("taskId", taskId);
			map.put("instanceId", instanceId);
			map.put("id", id);
			map.put("biz_id", id);
			return mv;
		} catch (Exception e) {
			e.printStackTrace();
			return new ModelAndView("/proms/common/error");
		}
	}
	
	@RequestMapping("/handle")
	public ModelAndView handle(@PrincipalArgument User user,
			@RequestParam(value = "taskId") String taskId,
			@RequestParam(value = "instanceId") Long instanceId,
			@RequestParam(value = "id") Long id,
			ModelMap map) {
		Task ptask = this.taskService.getProjectIndexInfoTask(id);
		DataDict isTaskPlan = this.dataDictService.findUniqueByCode(Constants.DATA_DICT_CODE_TASKPLAN);
		if (null != isTaskPlan) {
			map.put("isTaskPlan", isTaskPlan.getRemark());
		} else {
			map.put("isTaskPlan", StringUtils.EMPTY);
		}
		map.put("task", ptask);
		map.put("taskId", taskId);
		TaskImpl task = this.jbpmService.getTask(taskId);
		// 判断任务的操作状态
		MyTask lastTask = this.myTaskService.queryLastTaskInfo(instanceId);
		if (lastTask.getOperateType().equals(OperateType.BACK.getIndex())) {
			// 判断第一个历史任务与当前任务是否一致
			MyTask firstTask = this.myTaskService.findFirstTaskInfo(instanceId);
			String firstTaskName = firstTask.getTaskName();
			Long firTaskUserId = firstTask.getTransactorId();
			if (task.getActivityName().equals(firstTaskName) && firTaskUserId.longValue() == user.getId().longValue()) {
				// 驳回至发起人，这时候办理页面应该可以修改表单
				ModelAndView mv = new ModelAndView("proms/taskWorkflow/taskWorkflow_edit");
				Workflow workflow = this.workflowService.get(Constants.TASK_WORKFLOW_ID);
				Node node = this.nodeService.getNode(workflow.getDeploymentId(), Constants.TASK_NODE_2);
				List<Node> taskNodes = new ArrayList<Node>();
				taskNodes.add(node);
				mv.getModelMap().put("taskNodes", taskNodes);
				mv.getModelMap().put("deploymentId", workflow.getDeploymentId());
				String startTimeStr = DateFormatUtils.format(ptask.getStartTime(), "yyyy-MM-dd HH:mm:ss");
				String endTimeStr = DateFormatUtils.format(ptask.getEndTime(), "yyyy-MM-dd HH:mm:ss");
				mv.getModelMap().put("startTimeStr", startTimeStr);
				mv.getModelMap().put("endTimeStr", endTimeStr);
				mv.getModelMap().put("task", ptask);
				mv.getModelMap().put("instanceId", instanceId);
				mv.getModelMap().put("wfTaskId", taskId);
				return mv;
			}
		}
		Long deploymentId = (Long) jbpmService.getExecutionVariable(task.getExecutionId(), "deploymentId");
		map.put("deploymentId", deploymentId);
		ProInstance proInstance = proInstanceService.get(instanceId);
		map.put("proInstance", proInstance);
		Node curNode = nodeService.getNode(deploymentId, task.getActivityName());
		map.put("curNode", curNode);
		if(curNode.getFormTypeId() != null ) {
			// 节点表单
			Forms curForm = formsService.get(curNode.getFormTypeId());
			map.put("curForm", curForm);
			
		}
		// 操作列表
		List<Operate> operateList = this.operateService.queryNodeOperateList(curNode.getNodeId());
		map.put("operateList", operateList);
		Workflow workflow = workflowService.get(proInstance.getWorkFlowId());
		// 下一任务
		String flowXml_ = "";
		if(String.valueOf(deploymentId).equals(String.valueOf(workflow.getDeploymentId()))){
			flowXml_ = workflow.getFlowXml();
		}else{
			//读取
			flowXml_ = workflowService.getDefXmlByDeployId(String.valueOf(deploymentId));
		}
		
		List<Node> taskNodes = jbpmService.getNextActivity(task.getActivityName(), flowXml_, deploymentId);
		List<Node> taskNodesTemp = new ArrayList<Node>();
		taskNodesTemp.addAll(taskNodes);
		map.put("taskNodes", taskNodesTemp);

		map.put("instanceId", instanceId);

		Forms forms = formsService.get(proInstance.getFormTypeId());

		map.put("formUrl", forms.getHostUrl() + forms.getDetailUrl()+proInstance.getFormId());
		map.put("formHost", forms.getHostUrl());
		return new ModelAndView("proms/taskWorkflow/taskWorkflow_handle");
	}
	
	@ResponseBody
	@RequestMapping("/agree")
	public Result agree(@PrincipalArgument User user,
			@RequestParam(value = "id") Long id,
			@RequestParam(value = "taskId") String taskId,
			@RequestParam(value = "nextNode") String nextNodeName,
			@RequestParam(value = "userIds", required = false) String userIds,
			@RequestParam(value = "userNames", required = false) String userNames,
			@RequestParam(value = "advice", required = false) String advice) {
		try {
			Map<String, Object> result = this.jbpmTaskService
					.subWorkFlowSingle(taskId, nextNodeName, userIds, advice,
							user, OperateType.PASS.getIndex());
			boolean success = (Boolean) result.get("success");
			// 判断流程是否结束
			boolean isEnd = jbpmService.flowIsEnd(result.get("instanceId").toString(), (Node)result.get("nextNode"));
			if (isEnd) {
				Task task = this.taskService.get(id);
				task.setStatus(Constants.TASK_STATUS_AGREE);
				this.taskService.save(task);
			}
			return new Result(success, "保存成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false, "保存失败");
		}
	}
	
	@ResponseBody
	@RequestMapping("/reject")
	public Result reject(@PrincipalArgument User user,
			@RequestParam(value = "id") Long id,
			@RequestParam(value = "taskId") String taskId,
			@RequestParam(value = "advice", required = false) String advice) {
		try {
			Map<String, Object> result = this.jbpmTaskService.rejectWorkflowSingle(taskId, advice, user);
			boolean success = (Boolean) result.get("success");
			Task task = this.taskService.get(id);
			task.setStatus(Constants.TASK_STATUS_REJECT);
			this.taskService.save(task);
			// 判断流程是否结束
			/*boolean isEnd = jbpmService.flowIsEnd(result.get("instanceId").toString(), (Node)result.get("nextNode"));
			if (isEnd) {
				Task task = this.taskService.get(id);
				task.setStatus(Constants.TASK_STATUS_REJECT);
				this.taskService.save(task);
			}*/
			return new Result(success, "保存成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false, "保存失败");
		}
	}
	
	@ResponseBody
	@RequestMapping("/refuse")
	public Result refuse(@PrincipalArgument User user,
			@RequestParam(value = "id") Long id,
			@RequestParam(value = "taskId") String taskId,
			@RequestParam(value = "advice", required = false) String advice) {
		try {
			String nextNodeName = Constants.TASK_NODE_END;
			Map<String, Object> result = this.jbpmTaskService.subWorkFlowSingle(taskId, nextNodeName, StringUtils.EMPTY, advice, user, OperateType.REFUSE.getIndex());
			boolean success = (Boolean) result.get("success");
			// 判断流程是否结束
			boolean isEnd = jbpmService.flowIsEnd(result.get("instanceId").toString(), (Node)result.get("nextNode"));
			if (isEnd) {
				Task task = this.taskService.get(id);
				task.setStatus(Constants.TASK_STATUS_REFUSE);
				this.taskService.save(task);
			}
			return new Result(success, "驳回成功");
		} catch (Exception e) {
			e.printStackTrace();
			return new Result(false, "驳回失败，请联系管理员");
		}
	}
	
	@RequestMapping("/taskWorkflowDetail")
	public ModelAndView taskWorkflowDetail(Long id) {
		ModelAndView mv = new ModelAndView("proms/taskWorkflow/taskWorkflow_detail");
		mv.getModelMap().put("biz_id", id);
		/*// 通过formId转换成instanceId
		ProInstance proInstance = this.proInstanceService.getByForm(id, Long.parseLong(Constants.TASK_FORM_TYPE));
		if (null != proInstance) {
			mv.getModelMap().put("instanceId", proInstance.getInstanceId());
		} else {
			mv.getModelMap().put("instanceId", StringUtils.EMPTY);
		}*/
		return mv;
	}
	
	@ResponseBody
	@RequestMapping("/queryTaskDetailList")
	public EasyuiPagination<MyTask> queryTaskDetailList(EasyuiPage<MyTask>page, Long id) {
		Page<MyTask> tasks = this.myTaskService.queryTaskDetailList(page, id, Long.parseLong(Constants.TASK_FORM_TYPE));
		return new EasyuiPagination<MyTask>(tasks);
	}
	
	@RequestMapping("/taskWorkflowChart")
	public ModelAndView taskWorkflowChart(Long id) {
		ModelAndView mv = new ModelAndView("/workflow/flowchart/flowchart");
		// 通过formId转换成instanceId
		ProInstance proInstance = this.proInstanceService.getByForm(id, Long.parseLong(Constants.TASK_FORM_TYPE));
		if (null != proInstance) {
			mv.getModelMap().put("instanceId", proInstance.getInstanceId());
		} else {
			mv.getModelMap().put("instanceId", StringUtils.EMPTY);
		}
		return mv;
	}
	
	@ResponseBody
	@RequestMapping("/invalid")
	public Result invalid(
			@PrincipalArgument User user, 
			@RequestParam(value="id") Long id,
			@RequestParam(value = "instanceId", required = false) Long instanceId) {
		try {
			this.taskService.invalid(user, id, instanceId);
			return Result.SUCCESS;
		} catch (Exception e) {
			e.printStackTrace();
			return Result.FAILURE;
		}
	}
}
